/*
 * PacMan.fx
 *
 * Created on 18/03/2010, 03:36:29 PM
 */

package util;

/**
 * @author Alex
 */

import javafx.scene.CustomNode;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.Node;
import util.Map;
import javafx.scene.transform.Rotate;
import util.Maze;

/**
 
 */

public class PacMan extends CustomNode, MovingObject {

   public var defaultImage: Image = Image {
      url: "{__DIR__}images/PacMan2.png"
    };

   // angles of rotating the images
   def rotationDegree = [180, 270, 0, 90];



   // images for animation
   def images = [
     defaultImage,
     Image {
        url: "{__DIR__}images/PacMan1.png"
      },
     defaultImage,
     Image {
        url: "{__DIR__}images/PacMan3.png"
      }
   ];

   // GUI image of the man
   var pacmanImage : ImageView = ImageView {
      x: bind imageX  - 13
      y: bind imageY  - 13
      image: bind images[currentImage]
        transforms: Rotate {
            angle: bind rotationDegree[currentDirection]
            pivotX: bind imageX
            pivotY: bind imageY
        }
      }


  // buffer to keep the keyboard input
  var keyboardBuffer: Integer = -1;

  // current direction of Pacman
  var currentDirection: Integer = MOVE_LEFT;

  public var eatenDots : Integer = 0;
  public var scores : Integer = 0;

   public override function create(): Node {
      return pacmanImage;
    }

   // handle animation of one tick
  public override function moveOneStep() {

     // handle keyboard input only when pac-man is at a point of the grid
     if ( currentImage==0 ){
       handleKeyboardInput();
     }
 
     if ( state == MOVING) {
  
        if ( xDirection != 0 )
          moveHorizontally();
  
        if ( yDirection != 0 )
          moveVertically();
  
        // switch to the image of the next frame
        if ( currentImage < ANIMATION_STEP - 1  )
          currentImage++
        else {
           currentImage=0;
           updateScores();
         }
      }
      maze.pacManMeetsGhosts();
   }

   // moving horizontally
   public function moveHorizontally() {

      moveCounter++;

      if ( moveCounter < ANIMATION_STEP ) {
         imageX += xDirection * MOVE_SPEED;
       }
      else {
         moveCounter = 0;
         x += xDirection;

         imageX = Map.calcGridX(x);

         // the X coordinate of the next point in the grid
         var nextX = xDirection + x;

        if ( y == 17 and ( nextX <= 1 or nextX >= 27) ) {
           if ( nextX < 0 and xDirection < 0 ) {
              x = Map.WIDTH-1;
              imageX = Map.calcGridX(x);
            }
           else
             if ( nextX > 27 and xDirection > 0) {
                x = 1;
                imageX = Map.calcGridX(x);
               }
         } else {
         // check if the character hits a wall
         if ( Map.getCellData(nextX, y) == Map.BLOCK ) {
            state = STOP;
          }
         }
       }
    }

   // moving vertically
   public function moveVertically() {

      moveCounter++;

      if ( moveCounter < ANIMATION_STEP ) {
         imageY += yDirection * MOVE_SPEED;
       }
      else {
         moveCounter = 0;
         y += yDirection;
         imageY = Map.calcGridX(y);

         // the Y coordinate of the next point in the grid
         var nextY = yDirection + y;

         // check if the character hits a wall
         if ( Map.getCellData(x, nextY) == Map.BLOCK ) {
            state = STOP;
          }
       }
    }

  // turn pac-man to the right
    public function moveRight(): Void {

        if ( currentDirection == MOVE_RIGHT ) return;

        var nextX = x + 1;

        if ( nextX >= Map.WIDTH) return;

        if ( Map.getCellData(nextX,y) == Map.BLOCK ) return;

        xDirection = 1;
        yDirection = 0;

        keyboardBuffer = -1;
        currentDirection = MOVE_RIGHT;

        state = MOVING;
    }

  // turn pac-man to the left
    public function moveLeft(): Void {

        if ( currentDirection == MOVE_LEFT ) return;

        var nextX = x - 1;

        if ( nextX <= 1) return;

        if ( Map.getCellData(nextX, y) == Map.BLOCK ) return;

        xDirection = -1;
        yDirection = 0;

        keyboardBuffer = -1;
        currentDirection = MOVE_LEFT;

        state = MOVING;
    }

  // turn pac-man going up
    public function moveUp(): Void {

        if ( currentDirection == MOVE_UP ) return;

        var nextY = y - 1;

        if ( nextY <= 1) return;

        if ( Map.getCellData(x,nextY) == Map.BLOCK ) return;

        xDirection = 0;
        yDirection = -1;

        keyboardBuffer = -1;
        currentDirection = MOVE_UP;

        state = MOVING;
    }

  // turn pac-man going down
    public function moveDown(): Void {

        if ( currentDirection == MOVE_DOWN ) return;

        var nextY = y + 1;

        if ( nextY >= Map.HEIGHT ) return;

        if ( Map.getCellData(x,nextY) == Map.BLOCK ) return;

        xDirection = 0;
        yDirection = 1;

        keyboardBuffer = -1;
        currentDirection = MOVE_DOWN;

        state = MOVING;
    }

  // handle keyboard input
    public function handleKeyboardInput(): Void {
        if ( keyboardBuffer < 0) return;

        if ( keyboardBuffer == MOVE_LEFT )
            moveLeft()
        else
            if ( keyboardBuffer == MOVE_RIGHT )
                moveRight()
            else
                if ( keyboardBuffer == MOVE_UP )
                    moveUp()
                else
                    if ( keyboardBuffer == MOVE_DOWN )
                        moveDown();
    }

    public function setKeyboardBuffer( k: Integer): Void {
        keyboardBuffer = k;
    }

     public function updateScores() : Void {
     if ( y != 14 or ( x > 0 and x < Map.WIDTH ) ) {
        var dot : Dot = Map.getDot( x, y ) as Dot ;

        if ( dot.dotType == Map.MAGIC_DOT and dot.visible) {
          maze.makeGhostsHollow();
        }

        if ( dot != null and dot.visible ) {
           scores += 10;
           dot.visible = false;
           eatenDots ++;
         }

      }
   }

   // place Pac-Man at the startup position for a new game
   public function resetStatus() {
      state = MOVING;
      currentDirection = MOVE_LEFT;
      xDirection = -1;
      yDirection = 0;

      keyboardBuffer = -1;
      currentImage = 0;
      moveCounter = 0;

      x=14;
      y=26;

      imageX = Map.calcGridX(x);
      imageY = Map.calcGridY(y);

      visible = true;
      start();
    }


  postinit {
     imageX = Map.calcGridX(x);
     imageY = Map.calcGridX(y);

     xDirection = 0;
     yDirection = -1;
     currentDirection = MOVE_UP;

     state = STOP;
     start();
  }

}
